package com.azier.util;

import com.azier.annotation.CompareField;

import java.lang.reflect.Field;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * 1 * @Author: luoj
 * 2 * @Date: 2019/8/20 11:52
 * 3
 */
public class ClassUtil {
    //反射获取实体类的Field，如果字段上有@FieldName注解，一并获取注解的内容
    //比较对象之间的差异，并将结果集存入map中
    /**
     * 反射获取类的Field
     *
     */
    public static List<Field> getFieldList(Class clazz){
        List<Field> fieldList = new ArrayList<>();
        Map<String,Field> fieldName = new HashMap<>();
        Class<?> c = clazz;
        while (c != null) {
            for (Field field : c.getDeclaredFields()) {
                CompareField compareField = field.getAnnotation(CompareField.class);
                if(compareField!=null&&compareField.ignore()){
                    //当有此注解并被声明不校验，则此字段直接不进入比对
                    fieldName.put(field.getName(),field);
                }else if(!fieldName.containsKey(field.getName())){
                    fieldList.add(field);
                    fieldName.put(field.getName(),field);
                }
            }
            c = c.getSuperclass();
        }
        return fieldList;
    }
    /**
     * 反射获取类的FieldMap,子类和父类同名的属性以子类为准
     *
     */
    public static Map<String,Field> getFieldMap(Class clazz){
        Map<String,Field> fieldMap = new HashMap<>();
        Map<String,Field> fieldName = new HashMap<>();
        Class<?> c = clazz;
        while (c != null) {
            for (Field field : c.getDeclaredFields()) {
                CompareField compareField = field.getAnnotation(CompareField.class);
                if(compareField!=null&&compareField.ignore()){
                    //当有此注解并被声明不校验，则此字段直接不进入比对
                    fieldName.put(field.getName(),field);
                }else if(!fieldName.containsKey(field.getName())){
                    fieldMap.put(field.getName(),field);
                    fieldName.put(field.getName(),field);
                }
            }
            c = c.getSuperclass();
        }
        return fieldMap;
    }

    /**
     * 反射获取类的Field
     *
     */
    public static List<Field> getFieldLinkList(Class clazz){
        List<Field> fieldList = new LinkedList<>();
        Map<String,Field> fieldName = new ConcurrentHashMap<>();
        Class<?> c = clazz;
        while (c != null) {
            for (Field field : c.getDeclaredFields()) {
                CompareField compareField = field.getAnnotation(CompareField.class);
                if(compareField!=null&&compareField.ignore()){
                    //当有此注解并被声明不校验，则此字段直接不进入比对
                    fieldName.put(field.getName(),field);
                }else if(!fieldName.containsKey(field.getName())){
                    fieldList.add(field);
                    fieldName.put(field.getName(),field);
                }
            }
            c = c.getSuperclass();
        }
        return fieldList;
    }
    /**
     * 反射获取类的FieldMap,子类和父类同名的属性以子类为准
     *
     */
    public static ConcurrentMap<String,Field> getFieldConcurrentMap(Class clazz){
        ConcurrentMap<String,Field> fieldMap = new ConcurrentHashMap<>();
        Class<?> c = clazz;
        while (c != null) {
            for (Field field : c.getDeclaredFields()) {
                CompareField compareField = field.getAnnotation(CompareField.class);
                if(compareField!=null&&compareField.ignore()){
                    //当有此注解并被声明不校验，则此字段直接不进入比对
                }else if(!fieldMap.containsKey(field.getName())){
                    fieldMap.put(field.getName(),field);
                }
            }
            c = c.getSuperclass();
        }
        return fieldMap;
    }

    /**
     * 反射获取类的FieldMap
     *
     */
    public static <T> Map<Field,Object> getFieldValueMap(T t) throws IllegalAccessException {
        if(t==null){
            return null;
        }
        Map<String,Field> fieldName = new HashMap<>();
        Map<Field,Object> fieldMap = new HashMap<>();
        Class<?> clazz = t.getClass();
        Class<?> c = clazz;
        while (c != null) {
            for (Field field : c.getDeclaredFields()) {
                CompareField compareField = field.getAnnotation(CompareField.class);
                if(compareField!=null&&compareField.ignore()){
                    //当有此注解并被声明不校验，则此字段直接不进入比对
                }else if(!fieldName.containsKey(field.getName())){
                    if (!field.isAccessible()) {
                        field.setAccessible(true);
                    }
                    Object value = field.get(t);
                    fieldMap.put(field,value);
                    fieldName.put(field.getName(),field);
                }
            }
            c = c.getSuperclass();
        }
        return fieldMap;
    }
}
